package com.dhcc.sdc.aop;

import com.alibaba.fastjson.JSONObject;
import com.dhcc.core.framework.constant.state.LogSucceed;
import com.dhcc.core.framework.constant.state.LogType;
import com.dhcc.core.framework.log.LogManager;
import com.dhcc.core.framework.util.HttpContextUtil;
import com.dhcc.core.framework.util.SpringContextHolder;
import com.dhcc.sdc.annotion.SdcBusiLog;
import com.dhcc.sdc.annotion.SdcBusiType;
import com.dhcc.sdc.busi.dao.SdcBusiOperationLogMapper;
import com.dhcc.sdc.busi.entity.SdcBusiOperationLogEntity;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.Date;
import java.util.Enumeration;
import java.util.TimerTask;

/**
 * 过程质控操作日志记录
 *
 * @ClassName: SdcLogAop
 * @Description: TODO
 * @author: syj
 * @date: 2023-03-06 10:29:13
 */
@Aspect
@Component
public class SdcLogAop {
    private static Logger log = LoggerFactory.getLogger(LogManager.class);

    private static final String LOG_CONTENT = "[类名]:%s <br/>[方法]:%s <br>[参数]:%s <br/>[  IP ]:%s";

    private String ipaddr;

    @Pointcut(value = "@annotation(com.dhcc.sdc.annotion.SdcBusiLog)")
    public void cutService() {
    }

    @Around("cutService()")
    public Object recordSdcBusiLog(ProceedingJoinPoint point) throws Throwable {
        // 先执行业务
        Object result = point.proceed();
        try {
            handle(point);
        } catch (Exception e) {
            log.error("日志记录出错!", e);
        }

        return result;
    }

    private void handle(ProceedingJoinPoint point) throws Exception {
        // 获取拦截的方法名
        Signature sig = point.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        String methodName = currentMethod.getName();

        // 获取拦截方法的参数
        String className = point.getTarget().getClass().getName();

        // 获取操作名称
        SdcBusiLog annotation = msig.getMethod().getAnnotation(SdcBusiLog.class);
        SdcBusiType bussinessName = annotation.sdcBusiType();

        HttpServletRequest request = HttpContextUtil.getRequest();

        JSONObject obj = new JSONObject();
        String content = buildeContent(point, methodName, request, obj);
        LogManager.me().executeLog(this.operationLog(bussinessName, className, methodName, content, obj, ipaddr));
    }

    /**
     * 日志内容
     *
     * @param joinPoint
     * @param methodName
     * @param request
     * @return
     */
    public String buildeContent(ProceedingJoinPoint joinPoint, String methodName, HttpServletRequest request, JSONObject obj) {
        String className = joinPoint.getTarget().getClass().getName();
        Object[] params = joinPoint.getArgs();
        StringBuffer bf = new StringBuffer();
        if (params != null && params.length > 0) {
            Enumeration<String> paraNames = request.getParameterNames();
            while (paraNames.hasMoreElements()) {
                String key = paraNames.nextElement();
                bf.append(key).append("=");
                bf.append(request.getParameter(key)).append("&");
                obj.put(key, request.getParameter(key));
            }
            if (StringUtils.isBlank(bf.toString())) {
                bf.append(request.getQueryString());
            }
        }
        log.info("REQUEST PARAMS :" + bf.toString());
        ipaddr = HttpContextUtil.getIp();
        return String.format(LOG_CONTENT, className, methodName, bf.toString(), ipaddr);
    }


    public static TimerTask operationLog(final SdcBusiType sdcBusiType, final String clazzName,
                                         final String methodName, final String msg, JSONObject obj, String ipaddr) {
        return new TimerTask() {
            @Override
            public void run() {
                try {
                    SdcBusiOperationLogEntity sdcBusiOperationLog = new SdcBusiOperationLogEntity();
                    sdcBusiOperationLog.setParams(obj.toJSONString());
                    if (obj.get("episodeId") != null) {
                        sdcBusiOperationLog.setEpisodeId(obj.getString("episodeId"));
                    }
                    if (obj.get("locId") != null) {
                        sdcBusiOperationLog.setLocId(obj.getString("locId"));
                    }
                    if (obj.get("modifyUserId") != null) {
                        sdcBusiOperationLog.setUserId(obj.getString("modifyUserId"));
                    }
                    if (obj.get("modifyUserName") != null) {
                        sdcBusiOperationLog.setUserName(obj.getString("modifyUserName"));
                    }
                    if (obj.get("qcentityId") != null) {
                        sdcBusiOperationLog.setQcentityId(obj.getLong("qcentityId"));
                    }
                    sdcBusiOperationLog.setLogType(sdcBusiType.getCode());
                    sdcBusiOperationLog.setLogName(sdcBusiType.getName());
                    sdcBusiOperationLog.setIpaddr(ipaddr);
                    sdcBusiOperationLog.setMessage(msg);
                    sdcBusiOperationLog.setResult(LogSucceed.SUCCESS.getMessage());
                    sdcBusiOperationLog.setCreateDate(new Date());
                    SdcBusiOperationLogMapper sdcBusiOperationLogMapper = SpringContextHolder.getBean(SdcBusiOperationLogMapper.class);
                    sdcBusiOperationLogMapper.insert(sdcBusiOperationLog);
                } catch (Exception e) {
                    log.error("创建日志异常!", e);
                }
            }
        };
    }
}
